/* 
 * Shuriken is the legal property of its developers. Please refer to the
 * COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Text;
using Shuriken.Core.Utils;
using Shuriken.Core.Store;
using Shuriken.Core.Store.Items;
using Shuriken.Core.Shell;
using Shuriken.Base; 

namespace Shuriken.Core.Store.Scanners
{
    public class StartMenuScanner : IScanner
    {
        private FileScannerHelper scanner;
        private List<ISubject> itemlist; 

        public StartMenuScanner()
        {
            scanner = new FileScannerHelper();

            scanner.Locations.Add(ShellUtils.folderStartMenu);
            scanner.Locations.Add(ShellUtils.folderCommonStartMenu);

            scanner.Level = FileScannerHelper.UNLIMITED_LEVEL; 

            scanner.Pattern.Add("*.lnk");
            scanner.Pattern.Add("*.appref-ms");

            itemlist = new List<ISubject>();
        }

        /// <summary>
        /// Evaluates a start menu link
        /// </summary>
        /// <remarks>
        /// A start menu link is valid if it is an existing file or a folder or it does not point to anything. 
        /// </remarks>
        /// <param name="fItem">Link File</param>
        /// <returns>True, if link is valid</returns>
        private bool EvaluateLink(Shell32.FolderItem fItem)
        {
            string target = ShellUtils.GetFolderItemPath(fItem);

            // Link does not point anywhere
            if (target.Length == 0)
            {
                return true;
            }

            // If it is an existing file 
            if (System.IO.File.Exists(target))
            {
                return true;
            }

            // If it is an existing folder 
            if (System.IO.Directory.Exists(target))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Building an image list of control panel items 
        /// </summary>
        /// <returns>list of icon indexes of cpl items</returns>
        private Dictionary<string, int> BuidImageList()
        {
            Shuriken.Core.Shell.ShellManager manager = Shuriken.Core.Shell.ShellManager.Instance;

            List<ShellItem> stList = manager.GetShellItemsList(ShellAPI.CSIDL.CSIDL_STARTMENU, true);
            stList.AddRange(manager.GetShellItemsList(ShellAPI.CSIDL.CSIDL_COMMON_STARTMENU, true));

            Dictionary<string, int> imgDictionary = new Dictionary<string, int>();

            foreach (ShellItem link in stList)
            {
                if (!imgDictionary.ContainsKey(link.Path))
                {
                    imgDictionary.Add(link.Path, link.IconIndex);
                }
            }

            return imgDictionary;
        }

        /// <summary>
        /// Scans an item and returns them as a list. 
        /// </summary>
        /// <returns>list of items scanned</returns>
        public List<string> Scan()
        {
            return scanner.Scan();
        }

 
        /// <summary>
        /// Creates an item
        /// </summary>
        /// <param name="pathToItem">path to the start menu item</param>
        /// <param name="ShellImageIndex">index of an image in the system shell image store</param>
        /// <returns>start menu item</returns>
        private ISubject CreateItem(string link, int ShellImageIndex)
        {
            Shell32.FolderItem fItem = null;

            fItem = ShellUtils.GetFolderItemFromFile(link);

            if (fItem == null)
            {
                Tracer.WriteWarning("Skipping null link : " + link);
                return null;
            }

            if (EvaluateLink(fItem))
            {
                StartMenuItem startMenuItem = new StartMenuItem(fItem);
                startMenuItem.Icon = ImageStore.AddSystemImageListIndex(ShellImageIndex);
                return startMenuItem;
            }

            return null;
        }

        #region IScanner Members

        /// <summary>
        /// list of items
        /// </summary>
        public List<ISubject> Items
        {
            get 
            { 
                return itemlist; 
            }
        }

        /// <summary>
        /// Updates the scanner
        /// </summary>
        public void Update()
        {
            List<string> items = scanner.Scan();
            Dictionary<string, int> images = BuidImageList();

            int index = -1;

            foreach (string link in items)
            {
                try
                {
                    if (images.ContainsKey(link))
                    {
                        index = images[link];
                        ISubject item = CreateItem(link, index);

                        if (item != null)
                        {
                            itemlist.Add(item);
                        }
                    }
                }
                catch
                {
                    continue;
                }
            }
        }

        #endregion

        #region IObject Members

        public string Name
        {
            get { return "Start Menu"; }
        }

        public string Description
        {
            get { return "Scanner for scanning start menu items."; }
        }

        public string Icon
        {
            get
            {
                return string.Empty;
            }
            set
            {
                
            }
        }

        #endregion
    }
}
